package edu.cornell.lassp.houle.RngPack;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

//
// RngPack 1.1a by Paul Houle
// http://www.honeylocust.com/RngPack/
//

/**
 * RandomSynchronized is a wrapper class that makes a random number generator safe for
 * multi-threaded operation by serializing access in time. For high-performance applications, it is
 * better for each thread to have it's own random number generator.
 * 
 * Note this class is declared serializable, but serialization won't be successful if it's wrapping
 * a non-serializable generator.
 * <P>
 * <A HREF="/RngPack/src/edu/cornell/lassp/houle/RngPack/RandomSynchronized.java"> Source code </A>
 * is available.
 * 
 * @author <A HREF="http://www.honeylocust.com/"> Paul Houle </A> (E-mail: <A
 *         HREF="mailto:paul@honeylocust.com">paul@honeylocust.com</A>)
 * @version 1.1a
 * 
 * @see RandomElement
 */

public abstract class RandomSynchronized
    extends RandomElement implements Serializable {

  private RandomElement rng;

  public RandomSynchronized(RandomElement rng) {
    this.rng = rng;
  }

  /**
   * Synchronized the raw() method, which is generally not threadsafe.
   * 
   * @see RandomJava
   * 
   * @return a random double in the range [0,1]
   */

  synchronized public double raw() {
    return rng.raw();
  }

  /**
   * This method probably isn't threadsafe in implementations, so it's synchronized
   * 
   * 
   * @param d array to be filled with doubles
   * @param n number of doubles to generate
   */

  synchronized public void raw(double d[], int n) {
    rng.raw(d, n);
  }

  /**
   * 
   * Wrapped so generators can override.
   * 
   * @param lo lower limit of range
   * @param hi upper limit of range
   * @return a random integer in the range <STRONG>lo</STRONG>, <STRONG>lo</STRONG>+1, ... ,<STRONG>hi</STRONG>
   * 
   */

  synchronized public int choose(int lo, int hi) {
    return rng.choose(lo, hi);
  }

  /**
   * 
   * Must be synchronized because state is stored in BMoutput
   * 
   * @return a random real with a gaussian distribution, standard deviation
   * 
   */

  synchronized public double gaussian() {
    return rng.gaussian();
  }

  /**
   * 
   * We wouldn't want some sneaky person to serialize this in the middle of generating a number
   * 
   */

  private synchronized void writeObject(final ObjectOutputStream out) throws IOException {
    // just so we're synchronized.
    out.defaultWriteObject();
  }

  private synchronized void readObject(final ObjectInputStream in) throws IOException,
      ClassNotFoundException {
    // just so we're synchronized.
    in.defaultReadObject();
  }

}
